home *** CD-ROM | disk | FTP | other *** search
- title MDIR.ASM - Memory resident DIRectory
-
- COMMENT |
-
- I've long desired a memory resident directory routine. This code began
- life as SD.ASM, whose original comments are reproduced below.
-
- The routine will put the directory on the "alternate" screen if
- two monitors are available. It does NOT check to see if the
- second monitor is actually installed.
-
- Usage:
- MDIR [2]
-
- where the [2] indicates that both a color and a monochrome
- monitor are available on the system. If you tell the routine
- that both are available, the directory will be printed to the
- monitor that is NOT currently being used.
-
- If only ONE monitor is installed, or if MDIR is executed without
- the '2' on the command line, then the directory will be shown on
- the monitor that is currently being used. If this is the case,
- MDIR will "save" the screen currently being used, and restore it
- when done.
-
- To use MDIR once it has been installed, it is activated by
- pressing either the <Alt><8> or the <Alt><9> key combinations
- together (where the number keys are those above the alpha keys on
- the keyboard, NOT the ones from the numeric keypad).
-
- If you press the <Alt><8> keys, the directory will be displayed
- in alphabetical order. If you press <Alt><9>, MDIR will prompt
- you for a "command line" to be used. The command line can
- duplicate a command given to the DOS DIR command. For example:
-
- [assume the <Alt><9> keys have been pressed together]
-
- MDIR prompt your response results
- ╔════════════╧═════════════╗ ╔═════════╧══════════╗ ╔═════════╧══════════╗
- command line (/H for help): *.* all files in the current
- directory
- \masm\files all files in the sub-
- directory named
- \masm\files
- *.pas any file in the current
- directory with the
- extension .PAS
- \masm\files\*.arc any file in the sub-
- directory named
- \masm\files with the
- extension .ARC
- b:*.* all files in the
- current directory
- on drive B:
-
- In addition, there are several options, detailed below, that are
- triggered by the / switch. /H given at the command line will list
- the options, which deal with including hidden & subdirectory files, and
- with the way in which the file list is sorted.
-
- The ability to handle path names was added to the original SD.ASM code.
- That approach was taken from:
-
- RED.ASM John Dickinson, "REDirecting Your Files",
- PC Magazine, Vol. 4, No. 4 (February 19, 1985)
- Moving files between directories without
- copy/erase
-
-
- CAVEATS:
- 1. Because MDIR reads information from the disk, avoid
- "triggering" this utility when an operating program
- is working with the disks -- results can be
- unpredictable (and fatal).
- 2. The code is set up to prevent MDIR from being triggered twice
- in a row -- a key other than the "trigger" keys must be pressed
- between uses.
- 3. The "trigger" keys are defined by EQUates near the top of the
- code -- (see KEY1 and KEY2). If they interfere as currently
- defined, please reassign 'em.
- 4. MDIR "sets up" the actual directory routines to use
- one of the unused interrupts (currently INT 67h) -- please use
- another interrupt if INT 67h interferes with any software that
- you are currently using. This interrupt approach was taken to:
- a: allow the directory routine to read the keyboard without
- calling its own routine;
- b: to help isolate the directory routine from the effects
- of pressing the <Alt><8 or 9> key combination again before
- the directory routine has completed its work; and
- c: it prevents MDIR from being REinstalled (MDIR will not
- install if Int 67h is already in use).
- 5. MDIR currently saves space for 256 directory entries
- (see the variable DIRBUF at the end of the stay-resident code).
- That's more than enough (by a factor of two) to display the files
- in my most outrageous directory -- but be forewarned, DOS can
- hold more than 256 entries in a subdirectory. The problem with
- increasing the storage space is that it requires 22 bytes per
- entry -- and the storage space becomes part of the resident file.
- Thus, if we increased DIRBUF to 1024 entries, an extra 16,896
- bytes of storage would stay resident when MDIR is installed. I
- prefer my resident utilities to be as small as possible (that's
- why I detest stay-resident programs written in high-level
- languages), so I've limited the space that mine requires.
- The routine currently does not bother to check if you've got
- more entries than space has been allocated for -- if you do,
- you'll crash MDIR's stack (see below), and possibly memory
- allocated to your operating program. In any case, if you use
- MDIR to display a directory with more entries than you've got
- reserved, death and destruction (or at least a good
- machine crash) can result.
- 6. The stack that MDIR uses when it is working is set at 150 words
- (see STACKTOP at the end of the stay-resident code). This
- should be phenominally generous.
- 7. MDIR does its best to trap disk errors -- it uses low-level
- BIOS routines to initially find out if the requested disk
- is ready. This allows MDIR to bypass the dread DOS error
- "disk not ready" -- which will cause a resident program to
- crash the machine. MDIR does NOT check to see if a hard drive
- is ready.
- 8. Some software stores information in the alternate pages of
- the video memory IF you are using a color/graphics adaptor
- (PC-Write, for example, stores its help screens in the memory
- of the other c/g pages). MDIR only saves the current video
- page, so you can scramble help screens when MDIR switches
- monitors.
- 9. MDIR doesn't check if a drive has been ASSIGNed. If you
- request a directory for drive B:, MDIR will look for physical
- drive B:.
-
- I've used this routine with a variety of software, including:
- Lotus' 123
- PC-Write
- PC-TALK
- TURBO Pascal
-
- This is one of several "two screen" utilities that I've been working on --
- since I've got two monitors, I am tired of effectively wasting one.
-
- MDIR may still have some bugs -- but then, you've got the source
- code, so please solve 'em (and let me know what you find). It
- ain't perfect, but it's small and efficient, and it seems to work for me.
-
- Please let me know about any bugs/comments that you have via
- Gene Plantz' IBBS, 312-882-4227.
- Mike Pechnyo
- ID1206
-
- <><><><><><><><><><><><><><><><> SD.ASM COMMENTS <><><><><><><><><><><><><><><>
-
- SD [d:][filename[.ext]] [options]
- [filespec] same as for DIR command
- [options] * /A - List hidden files.
- * /E - Without screen erase.
- * /W - wait when screen full.
- * /R - Include directory entries djm
- * /M - Display Modified entries only djm
- /X - Sort by extension.
- /S - Sort by size.
- /D - Sort by date/time.
- /N - Do not sort, original order.
- /H - Help - only display options djm
- Default = *.* sorted by name.ext with screen erase.
- * - Option may be combined with other options.
- This source file was created from an object file obtained
- from Gene Plantz's BBS in Chicago. The original file name
- was SD.HEX. I then used DEBUG and CAPTURE to get the first
- dis-assembly which was then edited with WORDSTAR to create
- a source that when assembled using MASM would duplicate the
- original object file.
- Comments have been added and I do hope they are helpful.
- I have made several modifications to the first version and
- am continuing to add comments. This source file is an
- excellent example for anyone wishing to learn 8086/8088
- assembly language. Use at your own risk and feel free to
- share this file with your friends.
- I certainly wish that John Chapman would publish his
- source file. His comments are sure to be more meaningful
- than mine could ever be. Some of the conversion routines
- are very elegant, but difficult to understand. As far as
- I'm concerned, PRINTDD is magic.
- Several modifications have been made. They are:
- 1. Filespecs are processed like DIR does.
- 2. No sort option was added. /N
- 3. Pause when screen full option added. /P changed to /W by DJM
- 4. Number of files found is printed.
- Ted Reuss
- Houston, TX
- SDIR Version 2.2 The GETFREE Subroutine was updated for DOS 2.0
- April 1, 1983 by Jack Y. Fong
- Changes are denoted by "JYF" at the end of changed lines.
- I (Dave Mc Laughlin) have also made several modifications: (V 3.0)
- Pause is now standard unless /P is entered to defeat
- Color is now supported on color monitors
- Free space is now reported at the bottom, along with
- directory total (to give an idea of how many diskettes
- may be required for backup)
- Volume and current directory are shown on the top line
- (my apologies to Capitol PC Club for removing their logo)
- Modified files are shown with a + sign in place of the .
- The /R option (show sub directory names) has been added
- The /P option was changed to /W(ait) and /M (modified only) added
-
-
- <><><><><><><><><><><><><><> SD.ASM COMMENTS END <><><><><><><><><><><><><><><>
-
- All ANSI.SYS calls have been removed from SD.ASM (done to speed up
- screen accesses) mp 1-6-86
-
- |
-
- SUBTTL EQUATES & STRUCTURES
- PAGE
- IF1
- DOSCALL MACRO FUNC,PARM1
- .xcref
- F_C = FUNC
- IFNB <PARM1>
- IF F_C EQ 2 OR (F_C GE 4 AND F_C LE 6) OR F_C EQ 14 OR F_C EQ 46
- MOV DL,PARM1
- ELSE
- MOV DX,OFFSET PARM1
- ENDIF
- ENDIF
- MOV AH,FUNC
- INT 21H
- .cref
- ENDM
- ENDIF
- .SALL ;supress all macro expansions
- ; PC-DOS INTERRUPT 21H FUNCTION CODES
- ;
- KEY1 equ 127 ; Alt 8 key (number key from on top of the keyboard)
- KEY2 equ 128 ; Alt 9 key (ditto)
- ; KEY1 will display a sorted directory of the
- ; current drive/subdirectory
- ; KEY2 will prompt for a "command line" which
- ; can be used to specify another subdirectory,
- ; drive, or files (wildcards in the file names
- ; are acceptable
- @CHROUT EQU 2 ;display char in DL
- @KEYIN EQU 8 ;kybd input w/o echo
- @STROUT EQU 9 ;print string terminated with $
- @CKEYIN EQU 12 ;clr kybd bufr & do inp.func in AL
- @VOLLAB EQU 11h ;search for first matching file, used for VOLUME LABEL
- @SRCH1 EQU 4Eh ;search for first dir entry mp
- @SRCH2 EQU 4Fh ;search for next dir entry mp
- @GETDSK EQU 25 ;get default disk drive
- @SETDTA EQU 26 ;set disk transfer addr
- @FATAD2 EQU 28 ;get FAT of drive # in DL
- @PARSEF EQU 41 ;parse filename
- @GETDTE EQU 42 ;get system date
- @GETTME EQU 44 ;get system time
- @DSKFSP EQU 36H ;get disk free space JYF
- @GETVER EQU 30H ;get version number JYF
- @GETDIR EQU 47H ;get directory djm
- CR EQU 0DH ;carriage return
- LF EQU 0AH ;line feed
- ; PC-DOS packed date <yyyyyyym mmmddddd>
- P_DTE RECORD P_YR:7,P_MO:4,P_DY:5
- ; PC-DOS packed time <hhhhhmmm mmmsssss>
- P_TME RECORD P_HR:5,P_MI:6,P_2S:5
- DIRNTRY STRUC ;directory entry structure
- LNK DW 0 ;ptr to next entry
- NAM DB 8 DUP(0) ;filename
- SEP DB '.' ;separator
- EXT DB 3 DUP(0) ;extension
- TME DW 0 ;time
- DTE DW 0 ;date
- SZL DW 0 ;low word of size
- SZH DW 0 ;high word of size
- DIRNTRY ENDS
-
- CODE_SEG segment
- assume cs:CODE_SEG,ds:CODE_SEG
- org 100h ; COM program format
- BEGIN: jmp SWAP_VECTORS ; Initialize vectors and attach to DOS
- ;
- getout: nop
- immed: db 0EAh
- redef16 label word
- ROM_KB_INT dd ? ; Double word to save address of
- ; ROM-BIOS keyboard interrupt
- INT24_LOC dd ? ; to save address of INT24 location
- video_hold dw 2000 dup(?) ; storage to hold the old screen
- in_use db 1
- shift_key db 0
- old_equip dw 0
- old_page db 0
- old_mode db 0
- old_pos dw 0
- old_size dw 0
- DIRWRK DB 64 DUP (' ') ;directory work area djm
- ROOT DB '* * ROOT * *',18 DUP (' ') ; djm
- DIRSW DB 0 ;0=this is not a directory entry djm
- TOTL DW 0 ;low order word of total size used djm
- TOTH DW 0 ;high order djm
- C1LNK DW 0 ;ptr to row 1, column 1
- C2LNK DW 0 ;ptr to row 1, column 2
- NBRFILS DW 0 ;# of files or detail lines
- SRTFLG DB 0 ;if = 0 then sort else no sort
- CLSFLG DB 0 ;if = 0 then clear screen
- EXTFLG DB 0 ;if <> 0 then sort by ext
- SIZFLG DB 0 ;if <> 0 then sort by size
- PSEFLG DB 0 ;if <> 0 then pause when screen is full
- DTEFLG DB 0 ;if <> 0 then sort by date/time
- MODFLG DB 0 ;if <> 0 then display modified only djm
- OPTFLG DB 0 ;if <> 0 then display options (no directory)djm
- command_len db 0
- command_line db 64 dup(0) ; storage for "command line" typed in
- source_path db 65 dup(0)
- DTA DB 43 DUP(0) ;Disk Transfer Area used
- old_FILNAME equ DTA+8
- old_FILTIME EQU DTA+30 ;directory search.
- old_FILSIZE EQU DTA+36
- old_FILATR EQU DTA+19
- FILNAME EQU DTA+30 ;by SRCHDIR for the
- FILTIME EQU DTA+22 ;directory search.
- FILSIZE EQU DTA+26
- FILATR EQU DTA+21
- other_dir db 0 ; 0 indicates neither drive nor path specified
- ; 1 = path only specified
- ; 2 = drive (and maybe path) specified
- retries db 0 ; # of times the disk was retried
- new_mask db 0
- new_mode dw 0 ; and for new mode, with video select chosen
- scrn_cols db 80 ; screen columns available mp
- old_mask dw 0FFFFh ; old equipment flag
- DIRLNK DW DIRBUF ;ptr to next opening in DIRBUF
- two_screens db 0 ; non-zero if more than one screen is available mp
- PERMPSE DB 1 ; permanent pause flag
- MAXDRIVE db 0 ; number of floppy drives
- DIR_ATTR db 16 ; directory attribute
-
- LPERSCR EQU 25 ;Lines per screen
- LINCNT DB LPERSCR-4 ;Number of lines left
- PSEMSG DB 'Strike a key when ready . . . $' ; djm
- HDNG1 DB 'Vol: '
- VOLLOC DB 13 DUP (' ') ;put volume label here djm
- DB 'Dir: '
- DIRLOC DB 27 DUP (' ') ;put directory name here djm
- DB 3 DUP (' '),'Date: ' ; djm
- D_MM DW '00' ;Month
- DB '/'
- D_DD DW '00' ;Day
- DB '/'
- D_YY DW '00' ;Year
- DB ' '
- DB 'Time: '
- T_HH DW '00' ;Hours
- DB ':'
- T_MM DW '00' ;Minutes
- DB CR,LF
- CRLF DB CR,LF,'$'
- HDNG2 DB 'Filespec.ext Bytes- --Last Change--$'
- DB 8 DUP(' ')
- SPACES DB '$'
- HDNG3 DB ' File(s)',8 DUP (' '),'$'
- HDNG5 DB ' Directory Total',9 DUP (' '),'$' ; djm
- HDNG6 DB ' Free Space'
- DB CR,LF,'$'
- OPTHDG DB ' S O R T E D D I R E C T O R Y',cr,lf
- DB CR,LF
- DB ' Display Options:',cr,lf
- DB ' /A Include hidden files',cr,lf
- DB ' /R Include directory names',cr,lf
- DB ' /M Show only files that have been ',cr,lf
- DB ' modified since last backup',cr,lf
- DB ' /E Don',39,'t erase screen before display',cr,lf
- DB ' /W Wait when screen is full',cr,lf,cr,lf
- DB ' Sort Options -- Sort by:',cr,lf
- DB ' /X eXtension',cr,lf
- DB ' /S Size',cr,lf
- DB ' /D Date and time',cr,lf
- DB ' /N No sort',cr,lf,'$'
-
- error_msg db 'There is a problem with drive '
- error_drive db ' :. (The door may be open).',13,10,10
- error_end db 'Please fix the problem, and press any key '
- db ' ..... OR reboot the computer',13,10,'$'
- abort_message db 13,10,10,'MDIR is aborting ...',13,10,'$'
-
- SUBTTL DISK TRANSFER AREA & FREE SPACE ENTRY DEFS
- PAGE
- XFCB DB -1,7 DUP(0),11 DUP('?'),25 DUP(0)
- old_ATTRIB EQU XFCB+6 ;file attribute
- old_DRVNBR EQU old_ATTRIB+1 ;drive # (1=A, 2=B, etc.)
- ATTRIB DB 0 ;file attribute
- DRVNBR DB 0 ;drive # (1=A, 2=B, etc.)
- FREESPC DW 0 ;Free space entry.
- DB '*FREE SPACE*',4 DUP(0)
- LOSIZE DW 0 ;of free space
- HISIZE DW 0 ;of free space
- command_question db 'command line (/H for help): $'
- DosSSeg dw 0
- DosSP dw 0
- command_location dw 0
- backslash db '\'
- stars db '*.*',0
- VALID_IN db 'abcdefghijklmnopqrstuvwxyz,;=',9
- VALID_OUT db 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',4 dup(32)
- VALID_NUM equ $ - VALID_OUT + 1
-
-
- ; MDIR_INT intercepts the keyboard interrupt and shows the directory
- ; if the KEY1 or KEY2 combination is pressed
- ;
-
- MDIR_INT proc near
- cmp ah,0 ; If Read Char request,
- jne bail_out ; check the in_use flag
- cmp cs:in_use,1 ; if MDIR is running, then use the
- je ChrRqst ; old handler to read the key
- bail_out:
- jmp getout ; else jump to the real routine
-
- ChrRqst:
- push ds ; save just about every
- push bx ; register that anyone ever
- push cx ; heard of
- push dx
- push es
- push si
- push di
- push bp
-
- mov bx,cs ; set up DS & ES
- mov ds,bx
- mov es,bx
-
- mov cs:DosSSeg,ss
- mov cs:DosSP,sp
-
- cli
-
- mov dx,ds ; set MDIR to use its own
- mov ss,dx ; stack
- mov sp,offset stacktop
-
- sti
-
- do_interrupt:
- int 67h ; call the interrupt using the old AH val
- cmp al,0 ; is an extended key code returned?
- jne return
- cmp ah,KEY1 ; sorted dir of current subdir
- je check_use
- cmp ah,KEY2 ; prompt for command line
- jne return
- check_use: ; see if the in_use flag is on
- cmp in_use,1 ; in_use = 1, MDIR not running
- jne go_again ; in_use <>1, MDIR currently working
- mov in_use,2
-
- mov shift_key,ah ; save the key code used to call MDIR
-
- call get_mdir ; and do the directory work
- go_again:
- mov ah,0 ; setup to read the keyboard again
- jmp short do_interrupt ; and loop back. This will not "release"
- ; until a key other than KEY1 or KEY2 has
- ; been pressed (that new key will be
- ; returned to whatever program was running
- ; when MDIR interrupted.
-
- return:
- mov in_use,1 ; MDIR is done
-
- cli
-
- mov ss,cs:DosSSeg ; reset the stack to wherever it was
- mov sp,cs:DosSP ; originally
-
- pop bp ; and pop all of the saved registers
- pop di ; (the new AX value is passed)
- pop si
- pop es
- pop dx
- pop cx
- pop bx
- pop ds
-
- iret ; and complete the interrupt call
- mdir_int endp
-
- GET_MDIR proc near ; show the directories
- ;
- ; set up the displays
- ;
- call init_video
- ;
- ; call directory routines
- ;
- DO_DIRECTORIES:
- call clear_vars ; clear any significant variables
- cmp shift_key,KEY2 ; which key was pressed?
- je A0a ; if KEY2, get a command line sequence
- call get_drive ; else process current directory
- mov command_location,offset stars
- jmp short A0b
- A0a:
- call get_command ; get and process the command line
- A0b:
- cmp retries,2
- jb A0c ; did the disk still fail?
- mov si,offset abort_message
- call show_line
- jmp short A99a ; show the pause message
- A0c:
- call srchdir ;Search directory
- cmp SRTFLG,0 ;Check if any sort
- jz A1 ; option selected.
- call lnkdirb ;Leave in original
- jmp short A2 ; directory order.
- A1: call srtdirb ;Sort by major key
- A2: mov al,optflg ;See if only options wanted djm
- or al,al ;See if H request for help djm
- jz A3 ;Wasn't djm
- mov si,offset OPTHDG
- call show_line
- jmp short A99 ;get out djm
- A3: call getfree ;Get free space
- call spltlst ;Set up for 2 columns
- call prthdng ;Print headings
- call prtdrvr ;Print detail lines
- call prtnfls ;Print # of files
- ;
- A99:
- cmp two_screens,1 ; if there are two screens, then reset
- je A100 ; the mode
- A99a:
- mov si,offset PSEMSG ;Display pause message.
- call show_line
- mov ah,0 ;Specify input function
- int 67h ;Wait for key press
- A100:
- call restore_video ; restore the screens
- ret
- GET_MDIR endp
-
- INIT_VIDEO proc near
- ;
- ; Save the current cursor position
- ;
- mov ah,3 ; Call Func 3 of Int 10H
- mov bh,0 ; to read cursor position
- int 10h ; (page zero for color screen)
- mov old_size,cx ; cursor start and stop lines
- mov old_pos,dx ; cursor row, column
- ;
- ; get the video status
- ;
- mov ah,0fh
- int 10h ; get video mode
- mov old_mode,al ; video mode
- mov old_page,bh ; current page
- cmp al,7 ; are we currently in monochrome mode?
- jne SAVE_SCREEN
- cmp old_size,0607h ; was the old cursor incorrectly set
- ; to the color cursor's size?
- jne SAVE_SCREEN
- mov old_size,0B0Ch ; start on 11, end on line 12
- ; note: DOS does not always set the proper cursor
- ; size upon startup - so this code catches the
- ; problem. See PC TECH JOURNAL, Dec., 1985,
- ; "The Dashed Cursor", Paul Pierce, p. 47.
- ;
- ; save the screen data
- ;
- SAVE_SCREEN:
- push ds
- mov ax,0b000h
- cmp old_mode,7 ; Did we switch from mono?
- je COPY_SCREEN ; Yes, move data from mono
- mov ax,0b800h
- add ah,old_page ; c/g card page addresses are:
- ; Mode 0 Address B800
- ; 1 B900
- ; 2 BA00
- ; 3 BB00
- COPY_SCREEN:
- mov ds,ax
- xor si,si ; Start at zero offset
- push cs ; mov from DS:SI to ES:DI
- pop es
- mov di,offset VIDEO_HOLD
- mov cx,2000 ; 2000 chars + attrs per screen
- cld ; Make sure move is 'forward'
- rep movsw ; Move Words with string instruction
- pop ds
- ;
- ; Screen switch routine - Establish calling argument (AL) for Int 10h
- ;
- cmp two_screens,1 ; if there are two screens, then go through
- je switch_screens1 ; the mode setting exercise
-
- mov ah,6 ; else clear the window
- mov al,0
- mov bh,7
- xor cx,cx ; upper left corner
- mov dh,24 ; row, column of lower right corner
- mov dl,79
- int 10h
- mov ah,2
- xor dx,dx
- mov bh,old_page
- int 10h ; set cursor to 0,0 position
- jmp short INIT_DONE ; since there was only one screen,
- ; the setup is done
-
- switch_screens1: ; set up the second screen
- push ds
- xor ax,ax ; set DS to 0
- mov ds,ax
- mov bx,word ptr ds:[410h] ; Current equipment flag to BX
- pop ds
- mov old_equip,bx
- mov cx,bx ; Make a copy of the equipment flag in CX
- and cx,30h ; Extract screen information
- xor bx,cx ; Erase current screen information in BX
- or bx,20h ; Set BX to color 80x25
- mov al,2 ; Set AL for B&W 80x25 in Int 10h
- cmp cx,30h ; Is current mono?
- je SET_MODE1 ; Yes, switch to color
- or bx,30h ; No, set BX for monochrome
- mov al,7 ; Set AL for monochrome in Int 10h
- SET_MODE1:
- push ds
- push ax
- xor ax,ax ; set DS to 0
- mov ds,ax
- mov word ptr ds:[410h],bx ; Write BX to equipment flag
- pop ax
-
- xor ah,ah ; Use Func 0 of Int 10h to
- int 10h ; change screen parameters
- pop ds
- INIT_DONE:
- ret
- INIT_VIDEO endp
-
- RESTORE_VIDEO proc near ; return the video to its original mode
- cmp two_screens,1 ; if there are two screens, then reset
- jne short skip_page ; the mode
-
- mov bx,old_equip
- push ds ; save DS for use again
- xor ax,ax ; set DS to 0
- mov ds,ax
- mov word ptr ds:[410h],bx ; restore the original equipment flag
- pop ds
-
- mov al,old_mode ; restore the original video mode
- xor ah,ah ; Use Func 0 of Int 10h to
- int 10h ; change screen parameters
-
- cmp old_mode,7 ; is the screen monochrome?
- je skip_page
- mov ah,5
- mov al,old_page
- int 10h ; set the video page to the old value
- ;
- ; After screens are switched back, return the screen data
- ;
- skip_page:
- mov ax,0b000h
- cmp old_mode,7 ; Did we switch back to mono?
- je COPY_BACK ; yes, so copy to the mono screen
- mov ax,0b800h
- add ah,old_page ; restore to the proper video page
- COPY_BACK:
- mov es,ax
- xor di,di ; Start at zero offset
- push cs ; mov from DS:SI to ES:DI
- pop ds
- mov si,offset VIDEO_HOLD
- mov cx,2000 ; 2000 chars + attrs per screen
- cld ; Make sure move is 'forward'
- rep movsw ; Move Words with string instruction
- ;
- ; Restore Cursor position
- ;
- mov dx,old_pos ; restore the cursor position from the stack
- mov ah,2 ; Use Func 2 of Int 10h to restore
- mov bh,old_page
- int 10h
- ;
- ; Restore Cursor size
- ;
- mov cx,old_size ; restore the cursor size from the stack
- mov ah,1 ; Use Func 1 of Int 10h to set cursor
- int 10h
- ;
- ret
- RESTORE_VIDEO endp
-
- SHOW_LINE proc near ; a simple-minded procedure to duplicate
- ; the INT 21h function to print a string
- ; terminated by a $. The routine uses
- ; the low-level BIOS Int 10h call rather
- ; than the DOS call.
- push ax
- print_loop:
- mov al,byte ptr ds:[si]
- cmp al,'$'
- je print_done
- call show_char
- inc si
- jmp short print_loop
- print_done:
- pop ax
- ret
- SHOW_LINE endp
-
- SHOW_CHAR proc near ; print a character using BIOS Int 10h
- ; character should be in AL
- mov ah,0Eh
- int 10h ; tty write function
- ret
- SHOW_CHAR endp
-
- CLEAR_VARS proc near ; clear all pertinent variables, and
- ; set initial values where needed.
- push cs
- pop es ; set up the extra segment
- cld ; and make all moves forward
- mov di,offset dirwrk ; fill DIRWRK with spaces
- mov al,' '
- mov cx,64 ; bytes to clear
- rep stosb
- mov di,offset dirsw
- mov cx,offset new_mask
- mov bx,offset dirsw
- sub cx,bx
- xor ax,ax
- rep stosb
- mov di,offset xfcb ; and clear a series of variables to 0
- inc di
- mov cx,offset freespc
- mov bx,di
- sub cx,bx
- xor ax,ax
- rep stosb
- mov di,offset xfcb ; fill the FCB with question marks (?)
- add di,8
- mov al,'?'
- mov cx,11
- rep stosb
- mov di,offset volloc ; and fill the headings with spaces
- mov cx,13
- mov al,' '
- rep stosb
- mov di,offset dirloc
- mov cx,27
- mov al,' '
- rep stosb
- mov t_mm,'00' ; clear the header variables used
- mov t_hh,'00'
- mov d_dd,'00'
- mov d_mm,'00'
- mov d_yy,'00'
- mov scrn_cols,80 ; screen columns available
- mov old_mask,0FFFFh ; old equipment flag
- MOV ax,OFFSET DIRBUF ;Point to DIRBUF
- mov dirlnk,ax ; reset the pointer
-
- mov LINCNT,LPERSCR-4 ;Reset to # lines/screen
- mov al,PERMPSE
- mov PSEFLG,al
- ret
- CLEAR_VARS endp
-
- GET_DRIVE proc near ; get the current drive
- doscall @GETDSK ;AL <- default disk
- inc al ;Increment drive #
- mov DRVNBR,al ;Save drive #
- call check_drive
- ret
- GET_DRIVE endp
-
- CHECK_DRIVE proc near ; see if the requested drive (number
- ; stored in DRVNBR is available.
- ; Use the BIOS interrupt to avoid
- ; DOS errors, and read a sector from
- ; within the FAT (which ought to be
- ; good if the disk is to work)
- push bx
- push cx
- push dx
- cli
- mov al,DRVNBR
- cmp al,MAXDRIVE
- ja drive_checked ; don't check if we're looking at a hard drive
- ; assume the hard drive is OK and ready
- begin_check:
- mov cx,3
- recheck_loop:
- push cx
- mov bx,offset DIRBUF ; temporarily use the directory buffer
- ; ES:BX point to the input buffer
- mov ah,2 ; read sectors into memory
- mov al,1 ; # of sectors to read
- mov ch,0 ; track
- mov cl,4 ; sector to read -- somewhere in the FAT
- mov dh,0 ; head #
- mov dl,DRVNBR
- dec dl ; so that drive # is in the form 0=A, 1=B
- int 13h
- pop cx ; restore the count
- cmp ah,0
- je drive_checked ; CF=1 means that the read failed, so retry
- mov ah,0
- int 13h ; reset the drive
- loop recheck_loop
- inc RETRIES
- cmp RETRIES,1 ; see how many times we've been here
- ; IBM recommends trying a BIOS call 3 times
- ; to make sure the disk is ready. We
- ; give one retry if it doesn't work the
- ; first time. If it doesn't work the
- ; second time, MDIR aborts.
- ja drive_checked
- mov al,DRVNBR
- add al,'@'
- mov byte ptr error_drive,al
- mov si,offset error_msg ; show the error message
- call show_line
- mov ah,0
- int 67h ; wait for a keypress
- jmp short begin_check
- drive_checked:
- sti
- pop dx
- pop cx
- pop bx
- ret
- CHECK_DRIVE endp
-
- GET_COMMAND proc near ; get a "command line" in response
- ; to KEY2
- ; limitted editing (backspace and left
- ; arrow only both delete the last
- ; character in the command line)
- ; is supported
- push cs
- push cs
- pop ds
- pop es
-
- mov si,offset command_question
- call show_line
-
- mov di,offset command_line
- cld
- arg_loop:
- mov ah,0
- int 67h ; read the keyboard
- cmp al,0
- jnz check_key
- cmp ah,'K' ; was the left arrow pressed?
- jne arg_loop ; nope, so try again
- mov al,8 ; it was the left arrow, so process it as a
- ; backspace
- check_key:
- cmp al,13 ; was the carriage return hit?
- je arg_done ; if yes, the command line is done
-
- mov ah,0Eh ; if not, print the character using teletype mode
- int 10h ; tty write function
- cmp al,8 ; backspace ???
- jne other_key ; no, so process the key
- dec command_len ; yes, so decrement the counters,
- dec di ; and write a space + backspace
- mov al,' ' ; over the character on the
- mov ah,0eh ; screen
- int 10h
- mov al,8
- mov ah,0eh
- int 10h
- jmp short arg_loop
- other_key:
- inc command_len
- stosb ; save the byte
- jmp short arg_loop
- arg_done:
- mov al,0 ; put a zero byte at the end of the string
- stosb
- mov si,offset crlf ; and space down twice
- call show_line
- mov si,offset crlf
- call show_line
-
- CHECK_CMD_LINE:
- mov si,offset command_len ; command line length
- xor ch,ch ; Zero CH
- mov cl,[si] ; Move byte count to CL
- cmp cl,0
- jnz PARSE_CMD_LINE ; If CX is zero, there are no parameters
- jmp BLANK_EXIT ; so handle this as if it were a KEY1 call
-
- PARSE_CMD_LINE:
- mov dx,cx ; Save byte count in dx
- inc si ; Point to parameter area
- mov di,si ; Copy SI to DI for cleanup routine
- cld ; Set direction flag to forward
-
- CLEAN_PARMS: ; Change valid delimiters to blanks, lower to upper case
- lodsb ; Load each character to AL
- push di ; Save DI on stack
- mov di,offset VALID_IN ; Point to table of valid inputs
- push cx ; Save CX on stack
- mov cx,VALID_NUM ; Set CX to number of inputs to look for
- repne scasb ; See if any are in AL
- jcxz CLEAN_END ; If not, change nothing
- mov bx,VALID_NUM ; Set up BX to point to valid output
- sub bx,cx ; This will leave BX one off
- mov al,VALID_OUT [bx - 1] ; Load the valid output to AL
- CLEAN_END:
- cmp al,'/' ; is it the switch character?
- jne NOT_SWITCH ; (the switch character will
- pop cx ; terminate the directory request
- pop di ; of the command line)
- mov al,0 ; make the first command an ASCIIZ
- stosb
- mov si,di ; point to the rest of the command line
- call getargs ; and process the switch commands
- sub dx,cx ; correct the string length
- jmp short SWITCH_FOUND
- NOT_SWITCH:
- pop cx ; Restore CX
- pop di ; Restore DI
- stosb ; Store modified AL back to command line
- loop CLEAN_PARMS ; Loop until CX is zero
- ;
- SWITCH_FOUND:
- mov cx,dx ; Restore number of bytes in cmd line
- cmp cx,0
- jne PARSE_BLANKS
- jmp BLANK_EXIT
- PARSE_BLANKS: ; remove blanks
- mov al,' ' ; Set up to scan for first non-blank
- mov di,offset command_line ; Set DI to command_line
- FIND_PARMS: ; Start looking for parameters, load to program storage
- repe scasb ; Scan while blanks
- jnz FIX_DI ; if we've scanned everything
- jmp BLANK_EXIT
- FIX_DI:
- dec di ; Adjust it to first non-blank byte
- mov si,di
- inc cx ; Adjust CX to compensate
-
- mov di,offset source_path ; Set DI to parameter hold area
- STORE:
- lodsb ; Load each byte to AL
- cmp al,' ' ; Is it a blank?
- jz END_STORE ; Yes, end of this parameter
- stosb ; No, store the byte to hold area
- END_STORE:
- loopnz STORE ; Keep looking {must come after labelled
- ; jump to properly decrement CX}
- mov al,0
- stosb ; make the string an ASCIIZ
- mov other_dir,1 ; a path was specified
- mov di, offset source_path
- mov command_location,di
- cmp byte ptr [di],'\' ; a '\' only indicates the root dir
- jne NOT_ROOT ; has been requested
- inc di
- cmp byte ptr [di],0 ; is this just the root?
- jne NOT_ROOT
- mov si,offset stars ; get ready to move bytes
- mov cx,4
- rep movsb ; and copy the \*.* string
- call get_drive
- jmp short NOT_DIR
- NOT_ROOT:
- mov di, offset source_path + 1
- cmp byte ptr [di],':' ; has a drive been specified?
- je DRIVE_SPECD
- call get_drive
- jmp short COMMAND_GIVEN
- DRIVE_SPECD:
- mov other_dir,2 ; a drive (and maybe a path) has been
- dec di ; specified
- mov al,byte ptr [di]
- sub al,'@'
- mov DRVNBR,al ; save the drive number
- call check_drive ; see if it is a legitimate drive
- cmp retries,1 ; did the check fail?
- ja NOT_DIR
- inc di
- inc di
- cmp byte ptr [di],0 ; is the third byte the end-of-string?
- jne COMMAND_GIVEN
- mov si,offset backslash ; get ready to move bytes
- mov cx,5
- rep movsb ; and copy the \*.* string
- COMMAND_GIVEN:
- xor cx,cx
- mov cl,DIR_ATTR ; see if a subdirectory only was
- ; requested. (With the DOS DIR
- ; command, if \MASM\FILES is a
- ; subdirectory, then 'DIR \MASM\FILES'
- ; will display all the files contained
- ; in that subdirectory.
-
- DOSCALL @SETDTA,DTA ;Set DTA for dir. search
- mov ah,@srch1
- mov dx,command_location
- int 21h
- or al,al
- jnz NOT_DIR
- mov al,DIR_ATTR
- cmp FILATR,al ;did we get a directory back?
- je IS_DIR
- mov other_dir,0 ; no, so clear the flag
- jmp short NOT_DIR
- IS_DIR:
- mov al,0
- mov cx,65 ; > DOS command line
- mov di,offset source_path
- repne scasb ; look for the end-of-string
- dec di ; adjust DI to point to the last character
- mov si,offset backslash ; get ready to move bytes
- mov cx,5
- rep movsb ; and copy the \*.* string
-
- NOT_DIR:
- ret
-
- BLANK_EXIT: ; if a real command line wasn't specified,
- ; then use the default '*.*'
- mov command_location,offset stars ; default command line
- call get_drive ; get the current drive
- ret ; and bail out, because no parameters
- ; were entered
- GET_COMMAND endp
-
- GETARGS PROC NEAR ; get any arguments after the / switch
- ; SI needs to point to the ASCIIZ argument string
- B2: CMP BYTE PTR [SI],0
- je b99
- MOV AL,[SI] ;AL <- option letter
- mov byte ptr [si],' ' ; replace the character with a space
- CMP al,'/'
- Je B11 ;If not a slash
- AND AL,0DFH ;Force to upper-case
- CMP AL,'A' ;Hidden & system files?
- JNZ B31 ;Nope, try next one. djm
- OR ATTRIB,2+4 ;Hidden & system djm
- jmp short B11
- B31: CMP AL,'R' ;directory entries? djm
- JNZ B3 ;Nope, try next one. djm
- OR ATTRIB,10H ;Directory djm
- jmp short B11
- B3: CMP AL,'E' ;Without screen erase?
- JNZ B4 ;Nope, try next one.
- MOV CLSFLG,AL
- jmp short B11
- B4: CMP AL,'S' ;Sort by size?
- JNZ B5 ;Nope, try next one.
- MOV SIZFLG,AL
- jmp short B11
- B5: CMP AL,'D' ;Sort by date/time?
- JNZ B6 ;Nope, try next one.
- MOV DTEFLG,AL
- jmp short B11
- B6: CMP AL,'X' ;Sort by extension?
- JNZ B7 ;Nope, try next one.
- MOV EXTFLG,AL
- jmp short B11
- B7: CMP AL,'N' ;Original order?
- JNZ B8 ;Nope, try next one.
- MOV SRTFLG,AL
- jmp short B11
- B8: CMP AL,'W' ;Wait when screen full?
- JNZ B9 ;Nope, try next one.
- MOV PSEFLG,AL ; djm
- jmp short B11
- B9: CMP AL,'M' ;Just show modified entries? djm
- JNZ B10 ;Nope, try next one. djm
- MOV MODFLG,AL ; djm
- jmp short B11
- B10: CMP AL,'H' ;Just show options? djm
- JNZ B11 ;Nope, try next one djm
- MOV OPTFLG,AL ; djm
- B11: INC SI ;Point to next char
- jmp B2 ;Test for another param.
-
- B99: RET
- GETARGS ENDP
-
- SRCHDIR PROC NEAR ; do the actual directory search
- MOV BYTE PTR old_ATTRIB,8 ;get volume label djm
- mov al,DRVNBR
- mov byte ptr old_DRVNBR,al
- DOSCALL @SETDTA,DTA djm
- DOSCALL @VOLLAB,XFCB ;get volume label djm
- OR AL,AL ;found it? djm
- JNZ C11 ;none found djm
- MOV SI,OFFSET old_FILNAME ;source field djm
- MOV DI,OFFSET VOLLOC ;put in vol label djm
- MOV CX,11 ;length djm
- CLD ;clear direction flag djm
- REPZ MOVSB ;do it djm
- c11: xor cx,cx
- mov cl,ATTRIB
- DOSCALL @SETDTA,DTA ;Set DTA for dir. search
- mov ah,@srch1
- mov dx,command_location
- int 21h
- C1: OR AL,AL
- JZ C21 ;found djm
- JMP C2 ;not found - quit looking djm
- C21: mov si,offset FILNAME
- MOV AL,[SI] ;get first byte of entry djm
- CMP AL,'.' ;see if sub directory entry djm
- JNZ C211 ;no - process
- jmp C41
- C211:
- MOV BX,DIRLNK ;BX <- base of DIRBUF
- LEA DI,[BX].NAM
- MOV CX,13 ;13 bytes in the filename
- CLD
- mov al,' '
- rep stosb ; fill the filename with blanks
-
- lea di,[bx].sep
- MOV AL,FILATR ;load file attributes djm
- TEST AL,20h ;see if attr bit set djm
- JZ C3 ;no djm
- MOV BYTE PTR [DI],'+' ; djm
- JMP SHORT C4 ; djm
- C3: ; not modified - now see if /M set djm
- CMP MODFLG,0 ;see if /M set djm
- JNE C41 ;wasn't, so skip this entry djm
- TEST AL,10H ;see if directory entry djm
- JZ C31 ;no djm
- MOV BYTE PTR [DI],'-' ;store a minus for dir djm
- JMP SHORT C4 ; djm
- C31: MOV BYTE PTR [DI],'.' ; Store a period
- C4:
- LEA DI,[BX].NAM ; start at the filename again
- mov si,offset FILNAME
- MOV CX,SIZE NAM
- inc cx ; search 9 characters for the period, if needed
- C22: lodsb
- cmp al,0
- je C4c ; quit if the end of the string
- cmp al,'.'
- je C23 ; found the period in the file name
- stosb ;Move filename to DIRBUF
- loop C22
- C23:
- lea di,[bx].ext
- MOV CX,SIZE EXT
- C4a: lodsb
- cmp al,0
- je C4c ; found the period in the file name
- stosb ;Move ext to DIRBUF
- loop C4a
- C4c:
- lea di,[bx].tme
- MOV SI,OFFSET FILTIME
- MOVSW ;Move time to DIRBUF
- MOVSW ;Move date to DIRBUF
- MOV SI,OFFSET FILSIZE
- MOV AX,[SI] ;get number for size addition djm
- ADD TOTL,AX ;add djm
- MOVSW ;Move size to DIRBUF
- MOV AX,[SI] ;get high order djm
- ADC TOTH,AX ;add djm
- MOVSW
- ADD BX,SIZE DIRNTRY ;Point to next entry
- MOV DIRLNK,BX ;Save ptr
- INC NBRFILS ;Increment file count
- C41: DOSCALL @SRCH2 ;Search for next file
- JMP C1 ;Loop for next one
- C2: RET
- SRCHDIR ENDP
-
- SRTDIRB PROC NEAR ;Sorts directory entries in DIRBUF
- MOV DI,OFFSET DIRBUF ;Point to DIRBUF
- D1: CMP DI,DIRLNK ;Are there anymore?
- JNC D8 ;NO, exit
- MOV SI,OFFSET C1LNK ;Start with column 1 ptr
- D2: MOV BX,SI
- MOV SI,[BX] ;SI<-ptr to next entry
- OR SI,SI
- JZ D7 ;if link=0
- MOV AX,SI
- MOV DX,DI
- XOR CL,CL ;CL <- 0
- CMP CL,SIZFLG
- JNZ D5 ;If sort by size
- CMP CL,DTEFLG
- JNZ D4 ;If sort by date/time
- CMP CL,EXTFLG
- JNZ D3 ;If sort by ext
- LEA SI,[SI].NAM
- LEA DI,[DI].NAM
- MOV CX,1+SIZE NAM+SIZE EXT ;# of bytes
- JMP SHORT D6
- D3: LEA SI,[SI].EXT ;Sort by extension
- LEA DI,[DI].EXT
- MOV CX,SIZE EXT ;# of bytes
- JMP SHORT D6
- D4: LEA SI,[SI].DTE ;Sort by date/time
- LEA DI,[DI].DTE
- MOV CX,2 ;# of words
- STD
- REPZ CMPSW
- MOV DI,DX
- MOV SI,AX
- JBE D2
- JMP SHORT D7
- D5: LEA SI,[SI].SZH ;Sort by size
- LEA DI,[DI].SZH
- MOV CX,2 ;# of words
- STD
- REPZ CMPSW
- MOV DI,DX
- MOV SI,AX
- JBE D2
- JMP SHORT D7
- D6: CLD ;Sort by name.ext
- REPZ CMPSB
- MOV DI,DX
- MOV SI,AX
- JBE D2
- D7: MOV [DI],SI
- MOV [BX],DI
- ADD DI,SIZE DIRNTRY ;Point to next entry
- JMP D1
- D8: RET
- SRTDIRB ENDP
-
- ; LNKDIRB - LINKS ENTRIES IN DIRBUF
- LNKDIRB PROC NEAR ;LINK ENTRIES IN DIRBUF
- MOV DI,OFFSET DIRBUF
- MOV C1LNK,DI ;Point to 1st entry
- MOV CX,NBRFILS ;Set loop counter
- DEC CX
- LNK1:
- MOV BX,DI
- ADD DI,SIZE DIRNTRY ;Offset to next entry
- MOV [BX],DI ;Store ptr
- LOOP LNK1 ;Link next entry
- MOV [DI],CX ;Last ptr <- null
- RET
- LNKDIRB ENDP
-
- ; SPLTLST - SPLITS LINKED LIST IN HALF
- SPLTLST PROC NEAR
- MOV CX,NBRFILS ;Get # of entries
- SAR CX,1 ; and divide by 2
- JZ F2 ;if NBRFILS < 2
- ADC CL,0 ;Account for odd #
- MOV BX,OFFSET C1LNK
- F1: MOV BX,[BX] ;Chain thru list to
- LOOP F1 ; last row of column 1.
- MOV AX,[BX] ;Get ptr to 1st row of col 2
- MOV C2LNK,AX ; C2LNK <- R1,C2 ptr
- MOV [BX],CX ;Last row of col 1 <- null
- F2: RET
- SPLTLST ENDP
-
- GETFREE PROC NEAR ;cluster = allocation unit
- MOV DL,DRVNBR ;Get drive #
- PUSH DS ;Save DS
- DOSCALL @DSKFSP ;get disk free space JYF
- MUL BX ;AX (sectors/clustor) * BX (free cluJYF
- MOV DX,AX ; JYF
- MUL CX ;AX * CX (bytes/clustor) JYF
- ; JYF
- POP DS ;Restore DS
- MOV LOSIZE,AX ;Save the 32 bit
- MOV HISIZE,DX ; binary free space
- RET
- GETFREE ENDP
-
- PRTHDNG PROC NEAR
- DOSCALL @GETDTE ; CX<-year, DH<-month, DL<-day
- MOV AL,DH
- AAM
- XCHG AL,AH
- OR D_MM,AX ;Fold into month
- MOV AL,DL
- AAM
- XCHG AL,AH
- OR D_DD,AX ;Fold into day
- MOV AX,CX
- SUB AX,1900
- AAM
- XCHG AL,AH
- OR D_YY,AX ;Fold into year
- DOSCALL @GETTME ; CH<-hours, CL<-minutes
- MOV AL,CH ;AL<-binary hours
- AAM ;Convert AL to two
- XCHG AL,AH ; BCD digits in AX.
- OR T_HH,AX ;Fold into hours
- MOV AL,CL ;AL<-binary minutes
- AAM ;Convert AL to two
- XCHG AL,AH ; BCD digits in AX.
- OR T_MM,AX ;Fold into minutes
-
- cld ; make all moves forward
-
- mov di,offset dirloc
- mov si,offset command_line
- cmp other_dir,2 ; are both drive & dir specified?
- je G11
-
- mov al,DRVNBR ; if drive & path weren't spec'd
- add al,'@' ; put 'em into DIRLOC
- stosb
- mov al,':'
- stosb
-
- cmp other_dir,1 ; was only the dir specified?
- je G11
-
- MOV DL,DRVNBR ;set dl to current drive djm
- MOV SI,OFFSET DIRWRK ;point to work area djm
- DOSCALL @GETDIR ;get directory djm
- MOV AL,[SI] ;get 1st char djm
- CMP AL,0 ;see if no directory name djm
- JE G11a ;this is root directory djm
- mov al,'\'
- stosb
- jmp short G11
- G11a:
- MOV SI,OFFSET ROOT ;get * * ROOT * * djm
- G11:
- MOV CX,26 ; djm
- REPZ MOVSB ; djm
- mov si,offset HDNG1 ;Print main heading
- call show_line
- mov si,offset HDNG2 ;Print column 1 heading
- call show_line
- CMP WORD PTR C2LNK,0
- JZ G2 ;If not 2 columns
- mov si,offset SPACES-5 ;Print 5 spaces
- call show_line
- mov si,offset HDNG2 ;Print column 2 heading
- call show_line
- G2: mov si,offset CRLF ;Start a new line
- call show_line
- RET
- PRTHDNG ENDP
-
- PRTDRVR PROC NEAR ;Driver routine
- MOV BX,C1LNK
- OR BX,BX ;more to print?
- JZ H2 ; no, return
- MOV AX,[BX]
- MOV C1LNK,AX
- CALL PRTDTL ;print column one
- MOV BX,C2LNK
- OR BX,BX
- JZ H1 ;If no column 2 entry
- mov si,offset SPACES-5 ;print 5 spaces
- call show_line
- MOV AX,[BX]
- MOV C2LNK,AX
- CALL PRTDTL ;print column two
- H1: mov si,offset CRLF
- call show_line
- CMP PSEFLG,0 ;Check for pause option
- JZ PRTDRVR ;Nope, continue
- DEC LINCNT ;Decrement line counter
- JNZ PRTDRVR ;If page not full?
- MOV LINCNT,LPERSCR-2 ;Reset to # lines/screen
- mov si,offset PSEMSG ;Display pause message.
- call show_line
- MOV ah,0 ;Specify input function
- int 67h ;Wait for key press
- mov si,offset CRLF ;Set to new line
- call show_line
- JMP PRTDRVR ;Go do the next line
- H2: RET
- PRTDRVR ENDP
-
- PRTDTL PROC NEAR ;Prints file.ext, size, date & time
- MOV AL,[BX][0AH] ;get file.ext separator djm
- CMP AL,'-' ;see if minus inserted djm
- JNZ SHORT I0 ;not a Dir entry djm
- MOV BYTE PTR [BX][0AH],' ' ;clear minus sign djm
- OR DIRSW,1 ;set switch on djm
- I0: MOV CX,1+SIZE NAM+SIZE EXT
- SUB DI,DI ;DI <- 0
- I1: mov al,[BX+DI].NAM
- call show_char
- INC DI ;point to next char.
- LOOP I1 ;go do next char.
- CMP DIRSW,1 ;see if this is directory entry djm
- JNZ I11 ;no djm
- mov si,offset SPACES-8 ;print 8 spaces instead of size djm
- call show_line
- JMP SHORT I12
- I11: PUSH BX ;save entry base
- MOV SI,[BX].SZL ;SI <- low size
- MOV DI,[BX].SZH ;DI <- high size
- CALL PRINTDD ;Print size
- POP BX ;restore entry base
- I12: mov si,offset SPACES-2 ;print 2 spaces
- call show_line
- MOV AX,[BX].DTE ;AX <- packed date
- CALL PRTDTE
- mov si,offset SPACES-2 ;print 2 spaces
- call show_line
- MOV AX,[BX].TME ;AX <- packed time
- CALL PRTTME
- CMP DIRSW,1 ;see if switch on djm
- JNZ I2 ;no djm
- MOV DIRSW,0 ;shut off switch djm
- I2: RET
- PRTDTL ENDP
-
- PRINTDD PROC NEAR ;Prints a 32 bit integer in DI:SI
- XOR AX,AX ;Zero out the
- MOV BX,AX ; working
- MOV BP,AX ; registers.
- MOV CX,32 ;# bits of precision
- J1: SHL SI,1
- RCL DI,1
- XCHG BP,AX
- CALL J6
- XCHG BP,AX
- XCHG BX,AX
- CALL J6
- XCHG BX,AX
- ADC AL,0
- LOOP J1
- MOV CX,1710H ;5904 ?
- MOV AX,BX
- CALL J2
- MOV AX,BP
- J2: PUSH AX
- MOV DL,AH
- CALL J3
- POP DX
- J3: MOV DH,DL
- SHR DL,1 ;Move high
- SHR DL,1 ; nibble to
- SHR DL,1 ; the low
- SHR DL,1 ; position.
- CALL J4
- MOV DL,DH
- J4: AND DL,0FH ;Mask low nibble
- JZ J5 ;If not zero
- MOV CL,0
- J5: DEC CH
- AND CL,CH
- OR DL,'0' ;Fold in ASCII zero
- SUB DL,CL
- push ax
- mov al,dl
- call show_char
- pop ax
- RET ;Exit to caller
- PRINTDD ENDP
-
- J6 PROC NEAR
- ADC AL,AL
- DAA
- XCHG AL,AH
- ADC AL,AL
- DAA
- XCHG AL,AH
- RET
- J6 ENDP
-
- PRTDTE PROC NEAR ;Print packed date in AX as MM/DD/YY
- OR AX,AX
- JNZ K1 ;If date <> 0
- mov si,offset SPACES-8 ;Print 8 spaces
- call show_line
- RET
- K1: PUSH AX
- AND AX,MASK P_MO ;Mask the month,
- MOV CL,P_MO ; set shift count,
- SHR AX,CL ; right justify, &
- CALL PRTBCD ; print it.
- mov al,'/'
- call show_char
- POP AX
- PUSH AX
- AND AX,MASK P_DY ;Mask the day &
- CALL PRTBCD ; print it.
- mov al,'/'
- call show_char
- POP AX
- AND AX,MASK P_YR ;Mask the year,
- MOV CL,P_YR ; set shift count,
- SHR AX,CL ; right justify,
- ADD AX,80 ; add in year bias, &
- ; print it.
- call prtbcd
- ret
- PRTDTE ENDP
-
- PRTBCD proc near
- push ax
- AAM ;Convert AL to BCD
- OR AX,'00' ;Convert to ASCII
- PUSH AX
- mov al,AH ;High order digit
- call show_char
- POP AX
- call show_char
- pop ax
- RET
- PRTBCD ENDP
-
- PRTTME PROC NEAR ;Print packed time in AX as HH:MM
- OR AX,AX
- JNZ L1
- mov si,offset SPACES-5 ;Print 5 spaces
- call show_line
- RET
- L1: PUSH AX
- AND AX,MASK P_HR ;Mask the hours,
- MOV CL,P_HR ; set shift count,
- SHR AX,CL ; right justify, &
- CALL PRTBCD ; print it.
- mov al,':'
- call show_char
- POP AX
- AND AX,MASK P_MI ;Mask the minutes,
- MOV CL,P_MI ; set shift count,
- SHR AX,CL ; right justify, &
- CALL PRTBCD ; print it.
- RET
- PRTTME ENDP
-
- PRTNFLS PROC NEAR ;print number of files
- MOV SI,NBRFILS ;get # of files
- XOR DI,DI ;zero high order
- CALL PRINTDD ;Print # of files
- mov si,offset HDNG3
- call show_line
- MOV SI,TOTL ;set up total for print djm
- MOV DI,TOTH ; djm
- CALL PRINTDD ;print total space used by dir djm
- mov si,offset HDNG5 ; djm
- call show_line
- MOV SI,LOSIZE ;free space djm
- MOV DI,HISIZE ; djm
- CALL PRINTDD ;print free space djm
- mov si,offset HDNG6 ; djm
- call show_line
- RET
- PRTNFLS ENDP
- ;
- ; storage for directory entries
- ; please note - 256 entries is more than enough for anything
- ; on my system -- but if you've got directories with more entries
- ; please increase the space.
- ;
- EVEN
- DIRBUF DIRNTRY 256 dup(<>) ;Buffer for directory entries
- ;
- ; storage for a local stack
- dw 150 dup(0)
- stacktop label word
-
- ;
- ; This procedure initializes the new keyboard interupt vectors
- ;
- bad_intr db 'MDIR cannot be installed -- its interrupt'
- db ' vectors are already in use.$'
- SWAP_VECTORS proc near
- push ds ;Set up the
- xor ax,ax ; stack for a
- push ax ; return to DOS.
-
- push cs
- pop ds ; set up DS
- push cs
- pop es ; and ES to point to this section
-
- mov di,80h ; read the command line
- mov cl,es:[di]
- xor ch,ch ; clear the high byte
- cmp cl,2
- jb one_monitor ; if no command line
- mov al,' ' ; Set up to scan for first non-blank
- inc di ; Set DI to PC-DOS parameter pointer
- repe scasb ; Scan while blanks
- jz one_monitor ; if we've scanned everything
- mov al,es:[di-1] ; get the first non-blank byte
- cmp al,'2' ; are there two monitors?
- jne one_monitor
- mov two_screens,1 ; two monitors specified, so set the flag
- mov permpse,0 ; don't pause unless told to do so
-
- one_monitor:
- mov ax,0
- mov es,ax ;Clear esp. for Dos 3.0 bug
- push es ; save es
-
- mov ah,35h ; get the address if Int 67h
- mov al,67h
- int 21h
- mov ax,es
- cmp ax,0
- pop es ; restore the 0'd ES
- jne bad_exit ;get out if the int is already used
-
- mov ah,35h ; get the address of the keyboard interrupt
- mov al,16h ; keyboard function
- int 21h ; get interrupt vector
- mov word ptr ROM_KB_INT,bx ; save the offset
- mov word ptr ROM_KB_INT[2],es ; and the segment
-
- mov ah,25h ; reset the keyboard interrupt
- mov al,16h
- push cs
- pop ds ; DS:DX point to this routine
- mov dx,offset MDIR_INT
- int 21h ; set interrupt vector
-
- mov ah,25h ; and reset Int 67h to point to the
- mov al,67h ; old interrupt code
- mov dx, word ptr ROM_KB_INT
- mov bx, word ptr ROM_KB_INT[2]
- mov ds,bx ; DS:DX point to the new interrupt
- int 21h ; set interrupt vector
-
- int 11h ; get the equipment flag
- mov bx,ax ; save a copy of the flags
- and bl,1 ; are there any floppy disk drives?
- cmp bl,1
- jne stay_res
- and al,11000000b ; mask the count bits
- mov cl,6
- shr al,cl ; get the count
- inc al ; and set it so that 1 = 1 drive
- mov cs:MAXDRIVE,al ; and save the number of floppy drives
- ; for future reference
-
- stay_res:
- mov dx,offset bad_intr ; End of new resident program
- int 27h ; Terminate but stay resident
-
- bad_exit: ; whoops, something ain't kosher, so
- mov ah,9 ; print error message
- mov dx,offset bad_intr
- int 21h
- ret ; return to DOS
- SWAP_VECTORS endp
- CODE_SEG ends
- end BEGIN
- ;